package com.gmlive.gradle.versionlint

import com.gmlive.gradle.versionlint.cache.RepositoryCache
import com.gmlive.gradle.versionlint.library.Library
import com.gmlive.gradle.versionlint.repositories.MavenRemoteRepositoryHandler
import com.gmlive.gradle.versionlint.repositories.RepositoryResult
import okhttp3.OkHttpClient
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.logging.LogLevel
import org.gradle.api.plugins.JavaPlugin


class VersionsLintPlugin : Plugin<Project> {

    private var repositoryHandler: MavenRemoteRepositoryHandler? = null

    private val libraryMap: HashMap<String, Library> = hashMapOf()

    private val libraryList = mutableListOf<Library>()

    override fun apply(target: Project) {
        target.gradle.buildFinished {
            checkAllDependencies(target.rootProject)
        }
    }

    private fun checkAllDependencies(project: Project) {
        libraryList.clear()
        val projectIterator: Iterator<Project> = project.allprojects.iterator()
        while (projectIterator.hasNext()) {
            val temp = projectIterator.next()
            if (temp.configurations.size <= 0) {
                continue
            }
            println("=======Project Info:" + temp.name + " Start===========")
            val configurationIterator: Iterator<Configuration> = temp.configurations.iterator()
            while (configurationIterator.hasNext()) {
                val configurationTemp = configurationIterator.next()
                if (configurationTemp.name != JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME
                    && configurationTemp.name != JavaPlugin.API_CONFIGURATION_NAME
                    && configurationTemp.name != JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME
                ) {
                    continue
                }
                if (configurationTemp.allDependencies.size == 0) {
                    continue
                }
                val iterator: Iterator<Dependency> = configurationTemp.allDependencies.iterator()
                while (iterator.hasNext()) {
                    val dependency = iterator.next()
                    if (dependency.version == null || dependency.version == "unspecified") {
                        continue
                    }
                    println(
                        "dependency Info way:" + configurationTemp.name + " " +
                                "name:" + dependency.name +
                                " version:" + dependency.version
                    )
                    if (libraryMap[dependency.name] == null) {
                        val library =
                            Library(
                                dependency.group ?: "",
                                dependency.name,
                                dependency.version ?: ""
                            )
                        libraryMap[dependency.name] = library
                    }
                }
            }
            println("=======Project Info:" + temp.name + " End===========")
            println(" ")
        }
        val logger = project.logger
        libraryMap.forEach { (_, library) ->
            getRepositoryHandler().getNewVersionAvailable(library) { result ->
                val currentVersion = library.version
                if (result is RepositoryResult.NewVersionAvailable) {
                    logger.log(
                        LogLevel.ERROR,
                        "New version available: ${result.version}  currentVersion:$currentVersion"
                    )
                }
            }
        }
    }

    private fun getRepositoryHandler(): MavenRemoteRepositoryHandler {
        return repositoryHandler ?: run {
            MavenRemoteRepositoryHandler(OkHttpClient.Builder().build(), RepositoryCache())
                .also { handler -> repositoryHandler = handler }
        }
    }

}